using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using System;
using System.Linq;
using HybridCLR;

public class GameMain : MonoBehaviour
{
        // 需要补充元数据的DLL
    public static List<string> AOTMetaAssemblyNames { get; } = new List<string>()
    {
        "mscorlib.dll",
        "System.dll",
        "System.Core.dll", // 如果使用了System.Linq，需要这个
    };
    private static Dictionary<string, byte[]> s_assetDatas = new Dictionary<string, byte[]>();

    public static byte[] GetAssetData(string dllName)
    {
        return s_assetDatas[dllName];
    }
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(DownloadDll(this.StartGame));
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    IEnumerator DownloadDll(Action onDownloadComplete){
        var assets = new List<string>
        {
            "Assembly-CSharp.dll",
        }.Concat(AOTMetaAssemblyNames);
        foreach (var asset in assets)
        {
            var url = GetWebRequestPath(asset);
            Debug.Log($"start download asset:{url}");
            UnityWebRequest www = UnityWebRequest.Get(url);
            yield return www.SendWebRequest();
#if UNITY_2020_1_OR_NEWER
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.Log(www.error);
            }
#else
            if (www.isHttpError || www.isNetworkError)
            {
                Debug.Log(www.error);
            }
#endif
            else
            {
                byte[] assetData = www.downloadHandler.data;
                Debug.Log($"dll:{url}  size:{assetData.Length}");
                s_assetDatas[asset] = assetData;
            }
        }
        onDownloadComplete();
    }

    private string GetWebRequestPath(string asset)
    {
        var path = $"{Application.streamingAssetsPath}/{asset}";
        if (!path.Contains("://"))
        {
            path = "file://" + path;
        }
        return path;
    }

    void StartGame()
    {
        LoadMetadataForAOTAssembly();
#if !UNITY_EDITOR
        System.Reflection.Assembly.Load(GetAssetData("Assembly-CSharp.dll"));
#endif
        string path = Application.streamingAssetsPath + "/main.hotfix";
        AssetBundle prefabAb = AssetBundle.LoadFromFile(path);
        GameObject testPrefab = Instantiate(prefabAb.LoadAsset<GameObject>("Hotfix.prefab"));
    }

    // 补充元数据，在加载热更代码之前完成
    public void LoadMetadataForAOTAssembly()
    {
        HomologousImageMode mode = HomologousImageMode.SuperSet;
        foreach (var aotDllName in AOTMetaAssemblyNames)
        {
            byte[] dllBytes = GetAssetData(aotDllName);
            LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, mode);
            Debug.Log($"LoadMetadataForAOTAssembly:{aotDllName}. mode:{mode} ret:{err}");
        }
    }
}
